package cn.juque.datapipeline.helper;

import cn.hutool.core.date.DateUtil;
import cn.juque.common.constants.MessageEnum;
import cn.juque.common.exception.AppException;
import cn.juque.datapipeline.api.enums.GroupExecuteTypeEnum;
import cn.juque.datapipeline.constans.BusinessConstants;
import cn.juque.datapipeline.entity.TaskGroupInfo;
import cn.juque.datapipeline.service.impl.TaskGroupJobServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author juque
 * @version 1.0.0
 * <ul>
 *     <li>QuartzHelper</li>
 * </ul>
 * @date 2023-04-07 15:08:11
 **/
@Slf4j
@Component("quartzHelper")
public class QuartzHelper {

    private static final String QUARTZ_JOB_NAME = "quartz-job:>>";
    private static final String QUARTZ_JOB_GROUP_NAME = "group-job-quartz";

    private static final String QUARTZ_TRIGGER_NAME = "quartz-trigger:>>";
    private static final String QUARTZ_TRIGGER_GROUP_NAME = "group-job-quartz-trigger";

    @Resource
    private Scheduler scheduler;

    /**
     * 添加任务调度
     *
     * @param groupInfo 任务组信息
     */
    public void addJob(TaskGroupInfo groupInfo) {
        JobDetail jobDetail = JobBuilder
                .newJob(TaskGroupJobServiceImpl.class)
                .withDescription(groupInfo.getGroupName())
                .withIdentity(QUARTZ_JOB_NAME + groupInfo.getId(), QUARTZ_JOB_GROUP_NAME)
                // 传递任务组ID
                .usingJobData(BusinessConstants.GROUP_ID_KEY, groupInfo.getId()).build();
        Trigger trigger;
        if (GroupExecuteTypeEnum.CORN.getCode().equals(groupInfo.getExecuteType())) {
            trigger = TriggerBuilder.newTrigger()
                    .withDescription(groupInfo.getGroupName())
                    .withIdentity(QUARTZ_TRIGGER_NAME + groupInfo.getId(), QUARTZ_TRIGGER_GROUP_NAME)
                    .startNow().withSchedule(CronScheduleBuilder.cronSchedule(groupInfo.getCron())).build();
        } else {
            trigger = TriggerBuilder.newTrigger()
                    .withDescription(groupInfo.getGroupName())
                    .withIdentity(QUARTZ_TRIGGER_NAME + groupInfo.getId(), QUARTZ_TRIGGER_GROUP_NAME)
                    .startAt(DateUtil.offsetSecond(new Date(), groupInfo.getDelaySeconds()))
                    .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(groupInfo.getDelaySeconds())).build();
        }
        try {
            this.scheduler.scheduleJob(jobDetail, trigger);
            log.info("完成任务组【{}】的调度初始化", groupInfo.getGroupName());
        } catch (Exception e) {
            log.error("任务组【{}】调度任务初始化失败", groupInfo.getGroupName(), e);
            throw new AppException(MessageEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 删除任务
     *
     * @param groupId 任务组ID
     */
    public void deleteJob(String groupId) {
        JobKey jobKey = JobKey.jobKey(QUARTZ_JOB_NAME + groupId, QUARTZ_JOB_GROUP_NAME);
        try {
            this.scheduler.deleteJob(jobKey);
        } catch (Exception e) {
            log.error("任务ID【{}】调度任务删除失败", groupId, e);
            throw new AppException(MessageEnum.SYSTEM_ERROR);
        }
    }

    /**
     * job是否存在
     *
     * @param groupId 任务组ID
     * @return boolean
     */
    public Boolean existsJob(String groupId) {
        JobKey jobKey = JobKey.jobKey(QUARTZ_JOB_NAME + groupId, QUARTZ_JOB_GROUP_NAME);
        try {
            return this.scheduler.checkExists(jobKey);
        } catch (Exception e) {
            log.error("任务ID【{}】调度任务删除失败", groupId, e);
            throw new AppException(MessageEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 调度一次
     *
     * @param groupId 任务组ID
     */
    public void runOnce(String groupId) {
        JobKey jobKey = JobKey.jobKey(QUARTZ_JOB_NAME + groupId, QUARTZ_JOB_GROUP_NAME);
        try {
            this.scheduler.triggerJob(jobKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new AppException(MessageEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 暂停任务
     *
     * @param groupId 任务组id
     */
    public void pauseJob(String groupId) {
        JobKey jobKey = JobKey.jobKey(QUARTZ_JOB_NAME + groupId, QUARTZ_JOB_GROUP_NAME);
        try {
            this.scheduler.pauseJob(jobKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new AppException(MessageEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 恢复任务
     *
     * @param groupId 任务组ID
     */
    public void resumeJob(String groupId) {
        JobKey jobKey = JobKey.jobKey(QUARTZ_JOB_NAME + groupId, QUARTZ_JOB_GROUP_NAME);
        try {
            this.scheduler.resumeJob(jobKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new AppException(MessageEnum.SYSTEM_ERROR);
        }
    }
}
